<?php

/**
 * 命令行执行， TCP 客户端， WS 客户端
 * @noinspection ForgottenDebugOutputInspection
 */

require './comm.php';

use Workerman\Worker;
use Workerman\Lib\Timer;
use Workerman\Events\EventInterface;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
use Workerman\Http\Client as HttpClient;
use Workerman\Redis\Client as RedisClient;
use Workerman\Connection\AsyncTcpConnection;

//心跳间隔 x 秒
const HEARTBEAT_TIME = 10;

const SOCKET_URL = 'ws://127.0.0.1:9000';
//const SOCKET_URL = 'text://127.0.0.1:9021';

Worker::$logFile = ROOT_PATH . 'runtime/log/tcp.log';
Worker::$pidFile = ROOT_PATH . 'runtime/pid_tcp.log';

$worker = new Worker();

$worker->count = 1;

$worker->name = 'MySocketClient';

$worker->onWorkerStart = function ($worker)
{
    echo PHP_EOL. "#$worker->id 进程已启动" .PHP_EOL;

    $wsContext = [
        //设置访问对方主机的本地IP及端口(每个socket连接都会占用一个本地端口)
        'socket' => [
            //'bindto' => '0.0.0.0:9100', //IP必须是本机网卡IP，并且能访问对方主机，否则无效.
        ],
        'ssl' => [
            //请使用绝对路径
            //'local_cert'  => ROOT_PATH.'cert/cert.pem', // 本地证书路径。必须是 PEM 格式，并且包含本地证书及私钥。
            //'passphrase'  => ROOT_PATH.'cert/cert.key', // local_cert 文件的密码
            //'verify_peer' => false,
            //'allow_self_signed' => true, //如果是自签名证书需要开启此选项
        ]
    ];

    if (stripos(SOCKET_URL, 'text://') !== false) {
        $tcpConnection = new AsyncTcpConnection(SOCKET_URL);
    }
    elseif (stripos(SOCKET_URL, 'ws://') !== false) {
        $tcpConnection = new AsyncTcpConnection(SOCKET_URL, $wsContext);
    }
    elseif (stripos(SOCKET_URL, 'wss://') !== false) {
        $url = str_replace('wss://', 'ws://', SOCKET_URL);
        $tcpConnection = new AsyncTcpConnection($url, $wsContext);
        $tcpConnection->transport = 'ssl'; //PHP必须安装OpenSSL扩展。
    }


    $tcpConnection->onConnect = function ($connection)
    {
        echo PHP_EOL. 'TCP已连接到 ' . SOCKET_URL. PHP_EOL;
    };

    $tcpConnection->onMessage = function ($connection, $data)
    {
        //$data = gzdecode($data);

        echo PHP_EOL. 'TCP客户端收到消息：' .PHP_EOL. $data .PHP_EOL;

        if ($data === 'pong') {
            return;
        }
        elseif ($data === 'ping') {
            $connection->send('pong');
            return;
        }

        $arrayData = $data ? json_decode($data, true) : [];

        if (empty($arrayData) || empty($arrayData['action'])) {
            return;
        };

        switch ($arrayData['action']) {

            case 'pong':
                return;

            case 'ping':
                $connection->send('{"action": "pong", "count": "' . ($arrayData['count'] ?? 0) . '"}');
                break;

            default:
                //todo...
                break;
        }
    };

    $tcpConnection->onError = function ($connection, $code, $message)
    {
        echo PHP_EOL. "error: [$code] $message" .PHP_EOL;
        $connection->errorCode = $code;
        $connection->close();
    };

    $tcpConnection->onClose = function ($connection)
    {
        echo PHP_EOL. 'TCP连接 #' . $connection->id .' 断开'. PHP_EOL;

        if (empty($connection->errorCode)) {
            $connection->reConnect(0.6);
        }
    };

    $tcpConnection->connect();

    Timer::add(HEARTBEAT_TIME, function() use ($tcpConnection)
    {
        static $count = 0; $count++;
        $tcpConnection->send('{"action": "ping", "count": "' . $count . '"}');
    });
};

Worker::runAll();
